﻿using System;
using CommonServiceManager;
using CommonServiceManager.Configuration;
using Microsoft.Practices.Unity;

namespace UnityCommonServiceManagerAdapter.Configuration
{
	/// <summary>
	/// <see cref="IServiceConfigurator"/>
	/// </summary>
	public class UnityServiceConfigurator : IServiceConfigurator
	{
		private IUnityContainer unityContainer;

		/// <summary>
		/// Create the configurator and register it in the supporting <see cref="IUnityContainer"/>.
		/// </summary>
		/// <param name="serviceLocator">The current <see cref="IServiceLocator"/>.</param>
		/// <param name="unityContainer">The current <see cref="IUnityContainer"/>.</param>
		public UnityServiceConfigurator(IServiceLocator serviceLocator = null, IUnityContainer unityContainer = null)
		{
			ServiceLocator = serviceLocator;
			Container = unityContainer;
		}

		internal IServiceLocator ServiceLocator { set; get; }

		/// <summary>
		/// <see cref="IUnityContainer"/>
		/// </summary>
		public IUnityContainer Container
		{
			set
			{
				unityContainer = value;
				if (unityContainer != null)
				{
					unityContainer.RegisterInstance<IServiceConfigurator>(this);
				}
			}
			get
			{
				return unityContainer ??
							 (Container = ServiceLocator.GetInstance<IUnityContainer>());
			}
		}

		/// <summary>
		/// <see cref="IServiceConfigurator.RegisterInstance{TContract}(TContract,string)"/>
		/// </summary>
		public void RegisterInstance<TContract>(TContract instance, string implementationKey = null)
		{
			Container.RegisterInstance(implementationKey, instance);
		}

		/// <summary>
		/// <see cref="IServiceConfigurator.RegisterInstance(object,Type,string)"/>
		/// </summary>
		public void RegisterInstance(object instance, Type contractType, string implementationkey = null)
		{
			Container.RegisterInstance(contractType, implementationkey, instance);
		}

		/// <summary>
		///
		/// </summary>
		/// <typeparam name="TToConfigure"></typeparam>
		/// <param name="implementationKey"></param>
		/// <returns></returns>
		public IConfigurator<TToConfigure> Configure<TToConfigure>(string implementationKey = null)
		{
			return new UnityConfigurator<TToConfigure>(implementationKey)
			{
				ServiceLocator = ServiceLocator,
				Container = Container
			};
		}

		/// <summary>
		/// <see cref="IServiceConfigurator.RegisterType{TContract,TImplementation}(string)"/>
		/// </summary>
		public IConfigurator<TImplementation> RegisterType<TContract, TImplementation>(string implementationKey = null) where TImplementation : TContract
		{
			Container.RegisterType<TContract, TImplementation>(implementationKey);
			return Configure<TImplementation>(implementationKey);
		}
	}
}